#include<iostream>
#include<utility>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#include<list>
using namespace std;
namespace ylz
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;
		iterator begin()
		{
			return _str;
		}
		iterator end()
		{
			return _str + _size;
		}
		const_iterator begin() const
		{
			return _str;
		}
		const_iterator end() const
		{
			return _str + _size;
		}
		string(const char* str = "")
			:_size(strlen(str))
			, _capacity(_size)
		{
			cout << "string(char* str)-构造" << endl;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}
		void swap(string& s)
		{
			::swap(_str, s._str);
			::swap(_size, s._size);
			::swap(_capacity, s._capacity);
		}

		string(const string& s)
			:_str(nullptr)
		{
			cout << "string(const string& s) -- 拷贝构造" << endl;
			reserve(s._capacity);
			for (auto ch : s)
			{
				push_back(ch);
			}
		}

		// 移动构造
		string(string&& s)
		{
			cout << "string(string&& s) -- 移动构造" << endl;
			swap(s);
		}

		string& operator=(const string& s)
		{
			cout << "string& operator=(const string& s) -- 拷贝赋值" <<
				endl;
			if (this != &s)
			{
				_str[0] = '\0';
				_size = 0;
				reserve(s._capacity);
				for (auto ch : s)
				{
					push_back(ch);
				}
			}
			return *this;
		}
		//移动赋值
		string& operator=(string&& s)
		{
			cout << "string& operator=(string&& s) -- 移动赋值" << endl;
			swap(s);
			return *this;
		}
		~string()
		{
			cout << "~string() -- 析构" << endl;
			delete[] _str;
			_str = nullptr;
		}

		char& operator[](size_t pos)
		{
			assert(pos < _size);
			return _str[pos];
		}

		void reserve(size_t n)
		{
			if (n > _capacity)
			{
				char* tmp = new char[n + 1];
				if (_str)
				{
					strcpy(tmp, _str);
					delete[] _str;
				}
				_str = tmp;
				_capacity = n;
			}
		}

		void push_back(char ch)
		{
			if (_size >= _capacity)
			{
				size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
				reserve(newcapacity);
			}
			_str[_size] = ch;
			++_size;
			_str[_size] = '\0';
		}

		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}
		const char* c_str() const
		{
			return _str;
		}

		size_t size() const
		{
			return _size;
		}
	private:
		char* _str = nullptr;
		size_t _size = 0;
		size_t _capacity = 0;
	};
}

namespace ylz
{
	template <class T>
	struct ListNode
	{
		ListNode<T>* _next;
		ListNode<T>* _prev;
		T _data;
		ListNode(const T& data = T()) : _next(nullptr), _prev(nullptr), _data(data) {}
		//ListNode(T &&data) : _next(nullptr), _prev(nullptr), _data(move(data)) {}//移动构造
		ListNode(T&& data) : _next(nullptr), _prev(nullptr), _data(forward<T>(data)) {}//完美转发策略
		template<class ...Args>
		ListNode(Args&&... args)
			: _next(nullptr),
			_prev(nullptr),
			_data(std::forward<Args>(args)...)
		{

		}
	};
	template <class T, class Ref, class Ptr>
	struct ListIterator
	{
		typedef ListNode<T> Node;
		typedef ListIterator<T, Ref, Ptr> Self;
		Node* _node;
		ListIterator(Node* node) : _node(node) {}
		Self& operator++()
		{
			_node = _node->_next;
			return *this;
		}
		Ref operator*() { return _node->_data; }
		bool operator!=(const Self& it) { return _node != it._node; }
	};
	template <class T>
	class list
	{
		typedef ListNode<T> Node;

	public:
		typedef ListIterator<T, T&, T*> iterator;
		typedef ListIterator<T, const T&, const T*> const_iterator;
		iterator begin() { return iterator(_head->_next); }
		iterator end() { return iterator(_head); }
		void empty_init()
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
		}
		list() { empty_init(); }
		void push_back(const T& x) { insert(end(), x); }
		//移动构造
		void push_back(T&& x) { insert(end(), move(x)); }//右值引用的变量是左值
		iterator insert(iterator pos, const T& x)
		{
			Node* cur = pos._node;
			Node* newnode = new Node(x);
			Node* prev = cur->_prev;
			// prev newnode cur
			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
			return iterator(newnode);
		}
		iterator insert(iterator pos, T&& x)
		{
			Node* cur = pos._node;
			Node* newnode = new Node(move(x));//右值引用的变量是左值
			Node* prev = cur->_prev;
			// prev newnode cur
			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
			return iterator(newnode);
		}
		template<class ...Args>
		//这里的参数如果不加引用就会产生拷贝有额外消耗
		iterator emplace_back(Args&&... args)
		{
			return emplace(end(), std::forward<Args>(args)...);
		}

		template<class ...Args>
		//这里的参数如果不加引用就会产生拷贝有额外消耗
		iterator emplace(iterator pos, Args&&... args)
		{
			Node* cur = pos._node;
			Node* newnode = new Node(std::forward<Args>(args)...);//右值引用的变量是左值
			Node* prev = cur->_prev;
			// prev newnode cur
			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
			return iterator(newnode);
		}

	private:
		Node* _head;
	};
}




int main()
{
	//简单场景
	ylz::list<ylz::string> lt;

	ylz::string s1("111");//构造函数
	//lt.push_back(s1);//拷贝构造
	lt.emplace_back(s1);//拷贝构造
	cout << "***************************************" << std::endl;

	//lt.push_back(move(s1));//移动构造
	lt.emplace_back(move(s1));//移动构造,这里生成节点的时候并不会调用可变模板参数版本因为有现成的,所以编译器不会在自动生成
	cout << "***************************************" << std::endl;
	//lt.push_back("111");//构造+移动构造
	lt.emplace_back("222");//构造(直接拿着值去初始化节点)
	cout << "***************************************" << std::endl << std::endl;

	//复杂场景
	ylz::list<pair<ylz::string, int>> lt1;
	pair<ylz::string, int> kv("苹果", 1);//构造(自动调用自定义类型的构造)
	//lt1.push_back(kv);//拷贝构造
	lt1.emplace_back(kv);//拷贝构造
	cout << "***************************************" << std::endl;
	//lt1.push_back(move(kv));//移动构造
	lt1.emplace_back(move(kv));//移动构造,这里生成节点的时候并不会调用可变模板参数版本因为有现成的,所以编译器不会在自动生成
	cout << "***************************************" << std::endl;
	//lt1.push_back({"香蕉",2});//构造+移动构造
	lt1.emplace_back("橘子", 3);//构造
	cout << "***************************************" << std::endl << std::endl;
	////其实C++11以后引入了右值引用,深拷贝的差距没有见拷贝的差距打,因为先拷贝是以字节为单位拷贝的。

	return 0;
}